package com.clementheliou.cheliou.web.controller.user.subscription;

import java.io.Serializable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import com.clementheliou.cheliou.business.dataaccess.member.exception.EMailAlreadyUsedException;
import com.clementheliou.cheliou.business.functional.member.MemberFunctionalService;
import com.clementheliou.cheliou.dal.model.member.Member;
import com.clementheliou.cheliou.dal.model.member.enumeration.MemberLocale;
import com.clementheliou.cheliou.web.controller.user.UserBean;
import com.clementheliou.cheliou.web.util.date.DateUtils;
import com.clementheliou.cheliou.web.util.jsf.JSFUtils;

/**
 * Controller used to manage subscriptions requests.
 * 
 * @author Clément HELIOU (clement.heliou@gmail.com)
 * @see {@link Component};
 * @see {@link Scope};
 * @see {@link Serializable}.
 * @since 1.0
 */
@Controller
@Scope("request")
public class SubscriptionBean implements Serializable {

	/**
	 * UID for serialization.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @since 1.0
	 */
	private static final long serialVersionUID = 6685412875153424405L;

	/**
	 * Flag used to know if the form must be displayed or not.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @since 1.0
	 */
	private boolean formVisible = false;

	/**
	 * Value that is checked to avoid subscriptions by bots.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @since 1.0
	 */
	private int validationValue;

	/**
	 * Object that hold the data about the visitor that wants to subscribe.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @see {@link Member}.
	 * @since 1.0
	 */
	private Member candidate = new Member();

	/**
	 * Variable used to store the uncrypted password value.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @since 1.0
	 */
	private String password;

	/**
	 * Utilities about dates.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @see {@link Autowired};
	 * @see {@link DateUtils}.
	 * @since 1.0
	 */
	@Autowired
	private DateUtils dateUtils;

	/**
	 * Functional service about the members.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @since 1.0
	 */
	@Autowired
	private MemberFunctionalService memberFunctionalService;

	/**
	 * Utilities about <tt>JSF</tt>.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @see {@link Autowired};
	 * @see {@link JSFUtils}.
	 * @since 1.0
	 */
	@Autowired
	private JSFUtils jsfUtils;

	/**
	 * Utilities about the connected user.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @since 1.0
	 */
	@Autowired
	private UserBean userBean;

	/**
	 * Sends the subscription form values to the business service if these ones
	 * are valid. Checks the validation value consistency and catches exceptions
	 * incoming from service (especially, the duplicated email one).
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @return <code>null</code> because we stay on the same page.
	 * @since 1.0
	 */
	public String validateAndSubscribe() {

		if (dateUtils.getSumOfCurrentDateNumbers() != validationValue) {
			jsfUtils.addErrorMessage("user_subscription_form_validation_error");
		} else {

			final PasswordEncoder encoder = new Md5PasswordEncoder();
			candidate.setPassword(encoder.encodePassword(password, null));

			try {
				candidate.setLocale(MemberLocale.getMemberLocaleFromLocale(userBean.getCurrentLocale()));
				memberFunctionalService.addUserMember(candidate);
				jsfUtils.addInfoMessage("user_subscription_form_you_have_been_successfully_subscribed_and_can_now_user_your_credentials");
				clear();
			} catch (EMailAlreadyUsedException e) {
				jsfUtils.addErrorMessage("user_subscription_form_this_email_is_already_used");
			}

		}

		return null;
	}

	/**
	 * Clears all the form values.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @since 1.0
	 */
	private void clear() {
		candidate = new Member();
		password = null;
		validationValue = 0;
	}

	/*
	 * Getters & setters.
	 */

	public Member getCandidate() {
		return candidate;
	}

	public void setCandidate(Member candidate) {
		this.candidate = candidate;
	}

	public int getValidationValue() {
		return validationValue;
	}

	public void setValidationValue(int validationValue) {
		this.validationValue = validationValue;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean isFormVisible() {
		return formVisible;
	}

	public void setFormVisible(boolean formVisible) {
		this.formVisible = formVisible;
	}
}
